package com.winhxd.b2c.order.service.impl;

import com.winhxd.b2c.common.constant.BusinessCode;
import com.winhxd.b2c.common.domain.order.condition.OrderRefundCallbackCondition;
import com.winhxd.b2c.common.domain.order.condition.OrderRefundRebateCondition;
import com.winhxd.b2c.common.domain.order.enums.AfterSaleCompleteStatusEnum;
import com.winhxd.b2c.common.domain.order.enums.AfterSaleViewStatusEnum;
import com.winhxd.b2c.common.domain.order.enums.OrderOperationPropertyEnum;
import com.winhxd.b2c.common.domain.order.model.OrderAfterSaleDetail;
import com.winhxd.b2c.common.domain.order.model.OrderInfo;
import com.winhxd.b2c.common.domain.order.model.OrderLog;
import com.winhxd.b2c.common.domain.order.model.OrderRefundInfo;
import com.winhxd.b2c.common.domain.order.vo.OrderRefundRebateVO;
import com.winhxd.b2c.common.exception.BusinessException;
import com.winhxd.b2c.common.util.JsonUtil;
import com.winhxd.b2c.order.dao.*;
import com.winhxd.b2c.order.service.OrderAfterSaleDetailService;
import com.winhxd.b2c.order.service.OrderRefundService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;

/**
 * @author:zhangyanwei
 * @date:2019/1/10 20:55:21
 * @Description:退款回调接口实现类
 **/
@Service
public class OrderRefundServiceImpl implements OrderRefundService {

	private static final Logger logger = LoggerFactory.getLogger(OrderRefundServiceImpl.class);
	/**
	 * 退款成功
	 */
	private static final Short REFUND_STATUS_SUCCESS = 1;
	/**
	 * 退款失败
	 */
	private static final Short REFUND_STATUS_FAIL = 0;
	/**
	 * 退款回调状态：退款中
	 */
	private static final Short REFUND_STATUS_PROCESS = 0;
	/**
	 * 退款表中退款状态：退款中
	 */
	private static final Integer REFUND_PROCESS = 2;
	/**
	 * 更新成功
	 */
	private static final Integer UPDATE_SUCCESS = 1;
	/**
	 * 1-未发货退款
	 */
	private static final int WAIT_DELIVER_REFUND = 1;
	/**
	 * 2-已发货退货退款
	 */
	private static final int DELIVERED_REFUND = 2;
	/**
	 * 4-已完成退货退款
	 */
	private static final int FINISHED_REFUND = 4;

	@Resource
	private OrderAfterSaleDetailService orderAfterSaleDetailService;

	@Autowired
	private OrderRefundInfoMapper orderRefundInfoMapper;

	@Autowired
	private OrderAfterSaleDetailMapper orderAfterSaleDetailMapper;

	@Autowired
	private OrderRebateRecordMapper orderRebateRecordMapper;

	@Autowired
	private OrderInfoMapper orderInfoMapper;

	@Autowired
	private OrderLogMapper orderLogMapper;

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean orderRefundCallBack(OrderRefundCallbackCondition condition) {
		/**
		 * 回调需处理的逻辑：
		 *  1-修改退款表信息
		 * 	2-修改售后详细表(售后状态完成、页面状态)
		 * 	3-修改订单信息(是否闭环)
		 * 	4-返利、收益
		 * 	5-记录日志
		 */
		String log = "退款回调orderRefundCallBack--";
		logger.info(log + "参数：" + condition);
		String orderRefundNo = condition.getOutRefundNo();
		log += "--退款流水号--" + orderRefundNo;
		logger.info(log + "--开始");
		try {
			//获取退款信息
			OrderRefundInfo orderRefundInfo = this.getOrderRefundInfo(condition);
			//更新退款信息表
			Boolean refundInfoResult = this.updateRefundInfo(condition, orderRefundInfo);
			if (!refundInfoResult) {
				logger.error(log + "--更新退款信息表错误");
				throw new BusinessException(BusinessCode.CODE_460003);
			}
			//退款回调时，退款成功修改售后详细表、订单主表返利信息、SKU返利信息
			if (condition.getCallbackRefundStatus().intValue() == REFUND_STATUS_SUCCESS.intValue()) {
				logger.info("售后退款回调接口：退款成功回调开始：");
				Long afterSaleDetailID = this.getOrderRefundInfo(condition).getAfterSaleDetailId();
				//更新售后详细信息表
				Boolean afterSaleDetailRes = this.updateAfterSaleDetail(afterSaleDetailID, condition);
				if (!afterSaleDetailRes) {
					logger.error(log + "--更新售后详细信息表错误");
					throw new BusinessException(BusinessCode.CODE_460004);
				}
				//修改订单主表返利信息
				Boolean orderRes = this.updateOrderInfoRebate(orderRefundInfo);
				if (!orderRes) {
					logger.error(log + "--修改订单主表返利信息表错误");
					throw new BusinessException(BusinessCode.CODE_460010);
				}
				//修改SKU返利信息表
				Boolean rebateRes = this.updateRebateRecord(orderRefundInfo);
				if (!rebateRes) {
					logger.error(log + "--修改商品返利信息表错误");
					throw new BusinessException(BusinessCode.CODE_460006);
				}
				//保存日志
				this.saveRefundOrderLog(orderRefundInfo);
				//修改订单信息
				orderAfterSaleDetailService.updateOrderStatus(condition.getOrderNo());
				return true;
			} else {
				//回调状态为退款中和失败时，保存日志返并返回false，等待继续回调
				logger.info(log + "--退款回调为退款中和失败时，继续回调");
				this.saveRefundOrderLog(orderRefundInfo);
				return false;
			}
		} catch (Exception e) {
			logger.error(log + "退款回调异常参数{},异常{}",condition,e);
			return false;
		}
	}


	/**
	 * 修改订单主表返利信息
	 * @param orderRefundInfo
	 * @return
	 */
	private Boolean updateOrderInfoRebate(OrderRefundInfo orderRefundInfo){
		OrderRefundRebateCondition condition = new OrderRefundRebateCondition();
		this.buildRebateCondition(orderRefundInfo,condition);
		logger.info("售后退款回调接口：更新订单主表返利信息入参-{}", JsonUtil.toJSONString(condition));
		OrderRefundRebateVO vo = orderRebateRecordMapper.selectRebateByCondition(condition);
		OrderInfo orderInfo = orderInfoMapper.selectByOrderNo(orderRefundInfo.getOrderNo());
		this.buildOrderInfo(orderInfo, vo);
		logger.info("售后退款回调接口：更新订单主表返利信息实体-{}", JsonUtil.toJSONString(orderInfo));
		int res = orderInfoMapper.updateByPrimaryKeySelective(orderInfo);
		return res < UPDATE_SUCCESS ? false : true;
	}

	/**
	 * 构造OrderInfo
	 * @param orderInfo
	 * @param vo
	 */
	private void buildOrderInfo(OrderInfo orderInfo,OrderRefundRebateVO vo){
		orderInfo.setActualProfit(orderInfo.getActualProfit().subtract(vo.getActualProfit()));
		orderInfo.setActualIntegral(orderInfo.getActualIntegral()- vo.getActualIntegral());
	}

	/**
	 * 修改返利信息
	 * @param orderRefundInfo
	 * @return
	 */
	private Boolean updateRebateRecord(OrderRefundInfo orderRefundInfo){
		OrderRefundRebateCondition rebateCondition = new OrderRefundRebateCondition();
		this.buildRebateCondition(orderRefundInfo, rebateCondition);
		//退款成功，修改返利表;退款失败，返利表信息不动
		if(orderRefundInfo.getRefundStatus().intValue() == REFUND_STATUS_SUCCESS.intValue()){
			logger.info("售后退款回调接口：更新SKU返利信息入参-{}", JsonUtil.toJSONString(rebateCondition));
			int rebateRes = orderRebateRecordMapper.updateByOrderNoAndSKU(rebateCondition);
			return rebateRes < UPDATE_SUCCESS ? false : true;
		}else {
			return true;
		}
	}

	/**
	 * 构造返利入参
	 * @param orderRefundInfo
	 * @param condition
	 */
	private void buildRebateCondition(OrderRefundInfo orderRefundInfo, OrderRefundRebateCondition condition){
		condition.setOrderNo(orderRefundInfo.getOrderNo());
		condition.setSku(orderRefundInfo.getSkuId());
	}

	/**
	 * 构造日志信息
	 * @param orderRefundInfo
	 * @param orderLog
	 */
	private void buildOrderLog(OrderRefundInfo orderRefundInfo, OrderLog orderLog){
		String operationPropertity = this.getOperationPropertityByRefund(orderRefundInfo);
		orderLog.setOperationProperty(operationPropertity);
		orderLog.setOrderNo(orderRefundInfo.getOrderNo());
		orderLog.setSkuId(orderRefundInfo.getSkuId());
		orderLog.setCreated(new Date());
	}

	/**
	 * 更新退款信息表
	 * @param condition
	 * @return
	 */
	private Boolean updateRefundInfo(OrderRefundCallbackCondition condition, OrderRefundInfo orderRefundInfo){
		logger.info("售后退款回调接口：更新退款信息开始入参-{}", JsonUtil.toJSONString(condition));
		this.buildOrderRefundInfo(condition, orderRefundInfo);
		int res = orderRefundInfoMapper.updateByPrimaryKeySelective(orderRefundInfo);
		logger.info("售后退款回调接口：更新退款信息实体信息-{}", JsonUtil.toJSONString(orderRefundInfo));
		return res < UPDATE_SUCCESS ? false : true;
	}

	/**
	 * 根据退款流水号获取退款信息
	 * @param condition
	 * @return
	 */
	private OrderRefundInfo getOrderRefundInfo(OrderRefundCallbackCondition condition){
		OrderRefundInfo orderRefundInfo = orderRefundInfoMapper.selectRefundInfoByRefundNO(condition.getOutRefundNo());
		if(null == orderRefundInfo){
			throw new BusinessException(BusinessCode.CODE_460016);
		}
		if(condition.getCallbackRefundStatus().intValue() == REFUND_STATUS_SUCCESS.intValue()){
			orderRefundInfo.setRefundStatus(REFUND_STATUS_SUCCESS.intValue());
		}else if(condition.getCallbackRefundStatus().intValue() == REFUND_STATUS_PROCESS.intValue()){
			orderRefundInfo.setRefundStatus(REFUND_PROCESS.intValue());
		}else {
			orderRefundInfo.setRefundStatus(REFUND_STATUS_FAIL.intValue());
		}
		return orderRefundInfo;
	}

	/**
	 * 构造退款信息
	 * @param condition
	 * @param orderRefundInfo
	 */
	private void buildOrderRefundInfo(OrderRefundCallbackCondition condition, OrderRefundInfo orderRefundInfo){
		Date now = new Date();
		orderRefundInfo.setRefundPrice(condition.getCallbackRefundAmount());
		orderRefundInfo.setRefundStatus(condition.getCallbackRefundStatus().intValue());
		orderRefundInfo.setUpdatedBy(String.valueOf(condition.getCreatedBy()));
		orderRefundInfo.setUpdated(now);
		orderRefundInfo.setRefundTime(now);
	}

	/**
	 * 更新售后明细
	 * @param afterSaleDetailID
	 * @return
	 */
	private Boolean updateAfterSaleDetail(Long afterSaleDetailID,OrderRefundCallbackCondition condition){
		OrderAfterSaleDetail orderAfterSaleDetail = this.getOrderAfterSaleDetail(afterSaleDetailID);
		logger.info("售后退款回调接口：更新售后明细入参-{}", JsonUtil.toJSONString(condition));
		this.buildOrderAfterSaleDetail(orderAfterSaleDetail,condition);
		logger.info("售后退款回调接口：更新售后明细实体-{}", JsonUtil.toJSONString(orderAfterSaleDetail));
		int res = orderAfterSaleDetailMapper.updateByPrimaryKeySelective(orderAfterSaleDetail);
		return res < UPDATE_SUCCESS ? false : true;
	}

	/**
	 * 根据售后详细表ID获取售后详细信息
	 * @param afterSaleDetailID
	 * @return
	 */
	private OrderAfterSaleDetail getOrderAfterSaleDetail(Long afterSaleDetailID){
		return orderAfterSaleDetailMapper.selectByPrimaryKey(afterSaleDetailID);
	}

	/**
	 * 构造售后明细信息
	 * @param orderAfterSaleDetail
	 */
	private void buildOrderAfterSaleDetail(OrderAfterSaleDetail orderAfterSaleDetail,OrderRefundCallbackCondition condition){
		Date now = new Date();
		orderAfterSaleDetail.setCompleteStatus(AfterSaleCompleteStatusEnum.COMPLETED.getTypeCode());
		orderAfterSaleDetail.setCompleteTime(now);
		orderAfterSaleDetail.setUpdatedBy(String.valueOf(condition.getCreatedBy()));
		orderAfterSaleDetail.setUpdated(now);
		orderAfterSaleDetail.setViewStatus(AfterSaleViewStatusEnum.REFUNDED.getTypeCode());
	}

	/**
	 * 获取售后退款操作类型
	 * @param info
	 * @return
	 */
	private String getOperationPropertityByRefund(OrderRefundInfo info) {
		//退款成功,根据售后类型获取日志信息
		if (info.getRefundStatus().intValue() == REFUND_STATUS_SUCCESS.intValue()) {
			switch (info.getType()) {
				case WAIT_DELIVER_REFUND:
					return OrderOperationPropertyEnum.getDescByCode(OrderOperationPropertyEnum.AFTER_SALE_WAIT_DELIVERING_REFUND_FINISH.getPropertyCode());
				case DELIVERED_REFUND:
					return OrderOperationPropertyEnum.getDescByCode(OrderOperationPropertyEnum.AFTER_SALE_WAIT_RECEIVING_REFUND_FINISH.getPropertyCode());
				case FINISHED_REFUND:
					return OrderOperationPropertyEnum.getDescByCode(OrderOperationPropertyEnum.AFTER_SALE_FINISHED_REFUND_FINISH.getPropertyCode());
				default:
					return "";
			}
		//退款失败,根据售后类型获取日志信息
		} else if (info.getRefundStatus().intValue() == REFUND_STATUS_FAIL.intValue()) {
			switch (info.getType()) {
				case WAIT_DELIVER_REFUND:
					return OrderOperationPropertyEnum.getDescByCode(OrderOperationPropertyEnum.AFTER_SALE_WAIT_DELIVERING_REFUND_FAIL.getPropertyCode());
				case DELIVERED_REFUND:
					return OrderOperationPropertyEnum.getDescByCode(OrderOperationPropertyEnum.AFTER_SALE_WAIT_RECEIVING_REFUND_FAIL.getPropertyCode());
				case FINISHED_REFUND:
					return OrderOperationPropertyEnum.getDescByCode(OrderOperationPropertyEnum.AFTER_SALE_FINISHED_REFUND_FAIL.getPropertyCode());
				default:
					return "";
			}
		//退款中,根据售后类型获取日志信息
		} else {
			switch (info.getType()) {
				case WAIT_DELIVER_REFUND:
					return OrderOperationPropertyEnum.getDescByCode(OrderOperationPropertyEnum.AFTER_SALE_WAIT_DELIVERING_REFUND_PROCESS.getPropertyCode());
				case DELIVERED_REFUND:
					return OrderOperationPropertyEnum.getDescByCode(OrderOperationPropertyEnum.AFTER_SALE_WAIT_RECEIVING_REFUND_PROCESS.getPropertyCode());
				case FINISHED_REFUND:
					return OrderOperationPropertyEnum.getDescByCode(OrderOperationPropertyEnum.AFTER_SALE_FINISHED_REFUND_PROCESS.getPropertyCode());
				default:
					return "";
			}
		}
	}
	/**
	 * 保存日志
	 * @return
	 */
	private Boolean saveOrderLog(OrderLog orderLog){
		Integer res = orderLogMapper.insertSelective(orderLog);
		return res < UPDATE_SUCCESS ? false : true;
	}

	/**
	 * 保存售后退款回调日志
	 * @param orderRefundInfo
	 */
	private void saveRefundOrderLog(OrderRefundInfo orderRefundInfo){
		OrderLog orderLog = new OrderLog();
		this.buildOrderLog(orderRefundInfo,orderLog);
		logger.info("售后退款回调接口：保存日志-实体信息:-{}", JsonUtil.toJSONString(orderLog));
		Boolean saveLogRes = this.saveOrderLog(orderLog);
		if(!saveLogRes){
			logger.error("售后退款回调接口：保存日志失败 日志实体：{}",orderLog);
		}
	}
}
